#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Copyright © 2019-present Lenovo

This file is licensed under both the BSD-3 license for individual/non-commercial use and
EPL-1.0 license for commercial use. Full text of both licenses can be found in
COPYING.BSD and COPYING.EPL files.
"""

import datetime
from distutils.file_util import write_file
from os import chown, chmod
from pwd import getpwnam

from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID

user = getpwnam('ldap')


def generate_private_key():
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
    # Write our key to disk for safe keeping
    write_file('/etc/openldap/cacerts/server.key', [
        private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption(),
        )
    ])
    chmod('/etc/openldap/cacerts/server.key', 0400)
    chown('/etc/openldap/cacerts/server.key', user.pw_uid, user.pw_gid)

    return private_key


def generate_certificate(private_key):
    subject = issuer = x509.Name([
        x509.NameAttribute(NameOID.COUNTRY_NAME, u'CN'),
        x509.NameAttribute(NameOID.LOCALITY_NAME, u'Shanghai'),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Lenovo'),
        x509.NameAttribute(NameOID.COMMON_NAME, u'localhost'),
    ])

    cert = x509.CertificateBuilder().subject_name(
        subject
    ).issuer_name(
        issuer
    ).public_key(
        private_key.public_key()
    ).serial_number(
        x509.random_serial_number()
    ).not_valid_before(
        datetime.datetime.utcnow()
    ).not_valid_after(
        # Our certificate will be valid for 10 days
        datetime.datetime.utcnow() + datetime.timedelta(days=365)
    ).sign(private_key, hashes.SHA512(), default_backend())

    write_file(
        '/etc/openldap/cacerts/server.crt',
        [
            cert.public_bytes(serialization.Encoding.PEM)
        ]
    )
    chmod('/etc/openldap/cacerts/server.crt', 0400)
    chown('/etc/openldap/cacerts/server.crt', user.pw_uid, user.pw_gid)


if __name__ == '__main__':
    key = generate_private_key()
    generate_certificate(key)